package top.xana.acg.anime.decoder

import android.content.Context
import android.content.res.AssetFileDescriptor
import android.view.Surface
import android.view.SurfaceHolder
import androidx.annotation.IntRange
import com.aliyun.player.AliPlayer
import com.aliyun.player.AliPlayerFactory
import com.aliyun.player.IPlayer
import com.aliyun.player.IPlayer.OnLoadingStatusListener
import com.aliyun.player.IPlayer.OnRenderingStartListener
import com.aliyun.player.bean.ErrorInfo
import com.aliyun.player.bean.InfoBean
import com.aliyun.player.bean.InfoCode
import com.aliyun.player.nativeclass.CacheConfig
import com.aliyun.player.source.UrlSource
import com.android.iplayer.base.AbstractMediaPlayer

/**
 * @author xana
 * @date 2023/3/29 0029 23:59
 * @email cv4096@qq.com
 **/

class AliPlayer(context: Context) : AbstractMediaPlayer(context), IPlayer.OnPreparedListener,
    IPlayer.OnVideoSizeChangedListener,
    IPlayer.OnCompletionListener, IPlayer.OnErrorListener, IPlayer.OnInfoListener,
    IPlayer.OnSeekCompleteListener,
    OnRenderingStartListener, OnLoadingStatusListener {

    companion object {
        const val TAG = "AnimePlayer"

        const val cacheDir = ""

        const val HEADER_UA = "User_Agent"
        const val HEADER_REFERER = "Referer"
    }

    @IntRange(from = 0, to = 100)
    @Volatile
    private var buffer: Int = 0

    @Volatile
    private var isPlaying: Boolean = false

    @Volatile
    private var curPosition: Long = 0L


    private val aliPlayer: AliPlayer

    init {
        aliPlayer = AliPlayerFactory.createAliPlayer(context)
        initConfig()
    }

    // @link https://help.aliyun.com/document_detail/124714.html?spm=a2c4g.11186623.6.1083.2dbf2722XQM0Mr
    private fun initConfig() {
        with(aliPlayer.config) r@{
            mNetworkTimeout = 5000
            mNetworkRetryCount = 2
            mMaxDelayTime = 5000
            mMaxBufferDuration = 50000
            mHighBufferDuration = 3000
            mStartBufferDuration = 500

            if (cacheDir.isBlank()) return@r
            val cacheConfig = CacheConfig()
            cacheConfig.mEnable = true
            cacheConfig.mMaxDurationS = 500
            cacheConfig.mDir = cacheDir
            cacheConfig.mMaxSizeMB = 200
            aliPlayer.setCacheConfig(cacheConfig)
        }

        aliPlayer.setOnPreparedListener(this)
        aliPlayer.setOnVideoSizeChangedListener(this)
        aliPlayer.setOnCompletionListener(this)
        aliPlayer.setOnErrorListener(this)
        aliPlayer.setOnInfoListener(this)
        aliPlayer.setOnSeekCompleteListener(this)
        aliPlayer.setOnRenderingStartListener(this)
        aliPlayer.setOnLoadingStatusListener(this)
    }

    override fun setLooping(loop: Boolean) {
        aliPlayer.isLoop = loop
    }

    override fun setVolume(leftVolume: Float, rightVolume: Float) {
        aliPlayer.volume = maxOf(leftVolume, rightVolume)
    }

    override fun setBufferTimeMax(timeSecond: Float) {
    }

    override fun setSurface(surface: Surface?) {
        aliPlayer.setSurface(surface)
    }

    override fun setDisplay(surfaceHolder: SurfaceHolder?) {
        aliPlayer.setDisplay(surfaceHolder)
    }

    override fun setDataSource(dataSource: String?) {
        setDataSource(dataSource, null)
    }

    override fun setDataSource(dataSource: String?, headers: MutableMap<String, String>?) {
        if (!headers.isNullOrEmpty()) with(aliPlayer.config) {
            if (headers.containsKey(HEADER_UA)) mUserAgent = headers[HEADER_UA]
            if (headers.containsKey(HEADER_REFERER)) mReferrer = headers[HEADER_REFERER]
            customHeaders = headers.map { "${it.key}:${it.value}" }.toTypedArray()
        }
        aliPlayer.setDataSource(UrlSource().apply { uri = dataSource })
    }

    override fun setDataSource(dataSource: AssetFileDescriptor?) {

    }

    override fun setTimeout(prepareTimeout: Long, readTimeout: Long) {
        with(aliPlayer.config) {

        }
    }

    override fun setSpeed(speed: Float) {
        aliPlayer.speed = speed
    }

    override fun seekTo(msec: Long) = aliPlayer.seekTo(msec)

    override fun seekTo(msec: Long, accurate: Boolean) = aliPlayer.seekTo(msec)

    override fun isPlaying() = isPlaying

    override fun getCurrentPosition() = curPosition

    override fun getDuration() = aliPlayer.duration

    override fun getBuffer() = buffer

    override fun prepare() = aliPlayer.prepare()

    override fun prepareAsync() = aliPlayer.prepare()

    override fun start() = aliPlayer.start()

    override fun pause() = aliPlayer.pause()

    override fun stop() = aliPlayer.stop()

    override fun reset() = aliPlayer.reset()

    override fun onPrepared() {
        mListener?.onPrepared(this)
    }

    override fun onVideoSizeChanged(width: Int, height: Int) {
        mListener?.onVideoSizeChanged(this, width, height, 0, 0)
    }

    override fun onCompletion() {
        mListener?.onCompletion(this)
    }

    override fun onError(info: ErrorInfo?) {
        mListener?.onError(this, info?.code?.value ?: 0, 0)
    }

    override fun onInfo(info: InfoBean?) {
        when (val code = info?.code) {
            InfoCode.AutoPlayStart -> {
                isPlaying = true
            }
            InfoCode.BufferedPosition -> {

            }
            InfoCode.CurrentPosition -> {
                curPosition = info.extraValue
            }
            else -> mListener?.onInfo(this, code?.value ?: 0, info?.extraValue?.toInt() ?: 0)
        }
    }

    override fun onSeekComplete() {
        mListener?.onSeekComplete(this)
    }

    override fun onRenderingStart() {
        // 首帧渲染回调
    }

    override fun onLoadingBegin() {
        //缓冲开始
    }

    override fun onLoadingProgress(percent: Int, kbps: Float) {
        buffer = percent
    }

    override fun onLoadingEnd() {
        //缓冲结束
    }

    override fun release() {
        aliPlayer.release()
        super.release()
    }
}